/**
 * Created with CLion.
 * Description:
 * User: loong
 * Date: 2021-03-17
 * Time: 22:56
 */
#include "DiagramScene.h"
class Arrow;
DiagramScene::DiagramScene(QObject * parent)
    : QGraphicsScene(parent)
    , temp_line_(nullptr)
    , scene_mode_(SceneMode::MoveItem)
    , new_item_(nullptr)
    , root_item_(nullptr)
    //, left_button_down_(false)
    , mouse_press_point_(0, 0)
//, diagram_menu_(nullptr)
{
    //InitEvent();
}

DiagramScene::DiagramScene(QMenu * menu, QObject * parent)
    : QGraphicsScene(parent)
    , temp_line_(nullptr)
    , scene_mode_(SceneMode::MoveItem)
    , new_item_(nullptr)
    //, left_button_down_(false)
    , mouse_press_point_(0, 0)
//, diagram_menu_(menu)
{
    //InitEvent();
}

DiagramScene::~DiagramScene()
{
    qDeleteAll(items_.values());
    qDeleteAll(arrows_);
}

bool DiagramScene::isItemChange(int type)
{
    for(QGraphicsItem * item : selectedItems()) {
        if(item->type() == type)
            return true;
    }
    return false;
}

void DiagramScene::setLineColor(const QColor & color)
{
}

void DiagramScene::setTextColor(const QColor & color)
{
}

void DiagramScene::setItemColor(const QColor & color)
{
    //item_color_ = color;
    //if (isItemChange(DiagramBaseItem::Type)) {
    //    DiagramItem *item = qgraphicsitem_cast<DiagramItem *>(selectedItems().first());
    //    item->setBrush(item_color_);
    //}
}

void DiagramScene::setFont(const QFont & font)
{
    font_ = font;

    //if (isItemChange(DiagramTextItem::Type)) {
    //    QGraphicsTextItem *item = qgraphicsitem_cast<DiagramTextItem *>(selectedItems().first());
    //    //At this point the selection can change so the first selected item might not be a DiagramTextItem
    //    if (item)
    //        item->setFont(myFont);
    //}
}

void DiagramScene::SetDefaultMode()
{
    /*[1]: 创建item后，将鼠标形状复原为默认的箭头型 */
    auto view_list = views();
    if(!view_list.isEmpty() && nullptr != view_list.first())
        view_list.first()->setCursor(Qt::ArrowCursor);

    /*[2]: 恢复模式为默认的 MoveItem*/
    scene_mode_ = MoveItem;
}

void DiagramScene::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
    if(event->button() == Qt::LeftButton) {
        switch(scene_mode_) {
            case InsertRectItem:
                new_item_ = new DiagramBaseItem("Title");
                addItem(new_item_);
                //                items_ << new_item_;
                items_.insert(new_item_->data(DiagramBaseItem::IDData).toString(), new_item_);
                new_item_->setPos(event->scenePos());
                //                new_item_->SetItemPos(new_item_->pos());
                //                new_item_->SetItemSize(new_item_->shape().boundingRect().size());
                break;
            case InsertCircleItem:
                break;
            case InsertDiamondItem:
                break;
            case MoveItem:
                break;
            case InsertStraightLineItem:
            case InsertRightAngleLineItem:
                /*[]: 记录插入线段时的起点位置，作为临时item添加到scene中，此时该item只是一个点 */
                mouse_press_point_ = event->scenePos();
                //qDebug()<< "pos :" << mouse_press_point_;
                temp_line_         = new QGraphicsLineItem(QLineF(event->scenePos(), event->scenePos()));
                temp_line_->setPen(QPen(Qt::black, 2));
                addItem(temp_line_);
                break;
            default:;
        }
    }
    else if(event->button() == Qt::RightButton) {
        SetDefaultMode();
    }

    QGraphicsScene::mousePressEvent(event);
}

void DiagramScene::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
{
    if(scene_mode_ == MoveItem) {
        QGraphicsScene::mouseMoveEvent(event);
    }
    else if((scene_mode_ == InsertStraightLineItem || scene_mode_ == InsertRightAngleLineItem)
            && nullptr != temp_line_) {
        /*[]: 如果临时线段不为空的时候，将press事件中的点和和移动的位置点进行连接，更新临时线 */
        QLineF temp_line(temp_line_->line().p1(), event->scenePos());
        temp_line_->setLine(temp_line);
    }
}

void DiagramScene::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
{
    if(temp_line_ != nullptr
       && (scene_mode_ == InsertStraightLineItem || scene_mode_ == InsertRightAngleLineItem)) {
        /*[1]: 移除线段的开始点p1和结束点p2处的线段item，QGraphicsItem */
        QList<QGraphicsItem *> startItems = items(temp_line_->line().p1());
        if(!startItems.isEmpty())
            startItems.removeOne(temp_line_);
        QList<QGraphicsItem *> endItems = items(temp_line_->line().p2());
        if(!endItems.isEmpty())
            endItems.removeOne(temp_line_);

        /*[2]: 将临时线段删除，以获取开始和结束Item，临时线段已经无用 */
        removeItem(temp_line_);
        delete temp_line_;
        temp_line_ = nullptr;

        /*[TODO] 2021/4/12 9:02 loong : 此处注意除了箭头外，还有2个item，且textitem在baseitem之上，待修改 */
        /*[3]: 根据开始和结束item(此处注意除了箭头外，还有2个item，且textitem在baseitem之上，待修改)重新绘制带箭头的连接线 */
        if(!startItems.isEmpty() && !endItems.isEmpty()
           && startItems.last()->type() == DiagramBaseItem::Type
           && endItems.last()->type() == DiagramBaseItem::Type
           && startItems.last() != endItems.last()) {
            DiagramBaseItem * startItem = qgraphicsitem_cast<DiagramBaseItem *>(startItems.last());
            DiagramBaseItem * endItem   = qgraphicsitem_cast<DiagramBaseItem *>(endItems.last());

            Arrow::LineType type;
            if(scene_mode_ == InsertStraightLineItem)
                type = Arrow::StraightLine;
            else if(scene_mode_ == InsertRightAngleLineItem)
                type = Arrow::RightAngleLine;

            Arrow * arrow = new Arrow(startItem, endItem, type);
            startItem->AddChild(endItem);

            arrow->setZValue(-1000.0);
            addItem(arrow);
            arrows_ << arrow;
            arrow->UpdatePosition();
        }
    }

    QGraphicsScene::mouseReleaseEvent(event);
}

void DiagramScene::AddNewItem(DiagramBaseItem * _item)
{
    if(nullptr == _item)
        return;

    addItem(new_item_);

    items_.insert(new_item_->data(DiagramBaseItem::IDData).toString(), new_item_);
}

void DiagramScene::AddNewItem(const QString & _title_, bool _is_root)
{
    root_item_ = new DiagramBaseItem(_title_, _is_root);

    addItem(root_item_);

    items_.insert(root_item_->data(DiagramBaseItem::IDData).toString(), root_item_);
}

void DiagramScene::InitEvent()
{
    //connect(diagram_menu_,&QMenu::triggered,[=](QAction *action){
    //    if (nullptr != action && !action->text().isEmpty())
    //        return ;
    //
    //    if(action->text().compare("添加Item") == 0){
    //        SlotItemInserted();
    //    }
    //    else if(action->text().compare("删除Item") == 0){
    //
    //    }
    //    else if(action->text().compare("插入线") == 0){
    //
    //    }
    //
    //});
}

void DiagramScene::SlotNewRectItem()
{
    //    new_item_ = new DiagramBaseItem("");
    //    this->addItem(new_item_);
    //    //qDebug() << "pos :" << mouse_press_point_;
    //    new_item_->setPos(mouse_press_point_);
}

void DiagramScene::SlotNewCircleItem()
{
}

void DiagramScene::SlotNewDiamondItem()
{
}

void DiagramScene::contextMenuEvent(QGraphicsSceneContextMenuEvent * event)
{
    QGraphicsScene::contextMenuEvent(event);
}

void DiagramScene::DeleteArrowByStartItemID(const QString id)
{
    auto iter = arrows_.begin();
    while(iter != arrows_.end()) {
        if((*iter)->getStartItemId().compare(id) == 0
           || (*iter)->getEndItemId().compare(id) == 0) {
            this->removeItem((*iter));
            delete(*iter);
            /*[1]: 擦除指定迭代器 并更新迭代器位置 */
            iter = arrows_.erase(iter);
        }
        else
            ++iter;
    }
}

void DiagramScene::DeleteOneItem(DiagramBaseItem * _item)
{
    this->removeItem(_item);
    items_.remove(_item->data(DiagramBaseItem::IDData).toString());
    delete _item;
}

void DiagramScene::DeleteOneArrow(Arrow * arrow)
{
    this->removeItem(arrow);
    arrows_.removeOne(arrow);
    delete arrow;
}

void DiagramScene::UpdateArrow(const QString id)
{
    for(auto arrow : arrows_) {
        if(arrow->getStartItemId().compare(id) == 0)
            arrow->UpdatePosition();
    }
}

void DiagramScene::ToSqlString(DiagramBaseItem * _parent_item, QString & _result)
{
}

void DiagramScene::FromSqlString(QByteArray & query_result, bool _is_root)
{
}

void DiagramScene::SlotAutoAlignItem()
{
    auto align_items = this->selectedItems();
    if(align_items.isEmpty())
        return;

    auto item = qgraphicsitem_cast<DiagramBaseItem *>(align_items.last());
    ChildrenItemsRect(item);
}

QRectF DiagramScene::ChildrenItemsRect(DiagramBaseItem * _item)
{
    QPointF item_pos = _item->mapToScene(_item->pos());
    QRectF unit_rect = QRectF(item_pos,_item->polygon().boundingRect().size());
    unit_rect.moveCenter(item_pos);

    /*[1] 获取子节点的rect */
    for(auto child : _item->ChildItems()) {
        QRectF temp = ChildrenItemsRect(child);
        unit_rect = unit_rect.united(temp);
    }
    qDebug() << __FILE__ << __LINE__ << unit_rect;
    return unit_rect;
}
